import * as THREE from 'three-legacy';
import '@app-cad/common/utils/threeLoader';
import { OBJLoader } from 'three-legacy/examples/jsm/loaders/OBJLoader';
import { OrbitControls } from 'three-legacy/examples/jsm/controls/OrbitControls';
import { cadAppLog } from '@amcax/base';

export default class ModelPreviewer {
  private static instance: ModelPreviewer;
  private scene: THREE.Scene;
  private camera: THREE.Camera;
  private controls: OrbitControls;
  private renderer: THREE.WebGLRenderer;
  private directionLight: THREE.DirectionalLight;
  private animationFrameId: number;

  private constructor() {}
  public static getInstance(): ModelPreviewer {
    if (!ModelPreviewer.instance) {
      ModelPreviewer.instance = new ModelPreviewer();
    }
    return ModelPreviewer.instance;
  }

  public init(container: HTMLElement) {
    // ==== 创建场景 ====
    this.scene = new THREE.Scene();
    // ==== 创建一个点光源 ====
    // const light = new THREE.PointLight(0xffffff, 0.5)
    // light.position.set(150, 150, 150)
    // 环境光
    const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
    this.scene.add(ambientLight);
    this.directionLight = new THREE.DirectionalLight(0xffffff, 0.5);
    this.scene.add(this.directionLight);

    // ==== 创建一个透视投影相机对象 ====
    // this.camera = new THREE.PerspectiveCamera(10, 1, 1, 30000)
    this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 1, 30000);
    // 设置相机的位置
    this.camera.position.set(1, 1, 1);
    // 定义相机的视线 观察目标点的坐标
    this.camera.lookAt(0, 0, 0);

    // ==== 创建一个渲染器对象 ====
    this.renderer = new THREE.WebGLRenderer({
      antialias: true, // 抗锯齿
    });
    this.renderer.setPixelRatio(window.devicePixelRatio || 1);
    this.renderer.setClearColor(0xffffff);
    this.renderer.setSize(600, 600);
    this.renderer.render(this.scene, this.camera);

    // ==== 设置相机控件归到控制器 ====
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);
    // controls.addEventListener('change', () => {
    //     renderer.render(scene, camera)
    //     cadAppLog('camera.position', camera.position)
    // })
    this.controls.autoRotateSpeed = 5;
    this.controls.autoRotate = false;

    // const container = document.getElementById(containerId)
    container.appendChild(this.renderer.domElement);
  }

  public loadObj(url: string) {
    const loader = new OBJLoader();
    loader.load(url, (object) => {
      cadAppLog('加载完成时的回调函数', object);
      object.scale.set(0.01, 0.01, 0.01);
      // 设置模型材质
      object.traverse(function (child) {
        cadAppLog('traverse', child);
        if (child instanceof THREE.Mesh) {
          child.material = new THREE.MeshStandardMaterial({
            color: 0xcccccc,
            roughness: 1,
            side: THREE.DoubleSide,
          });
        }
      });

      // 添加模型到场景中
      this.scene.add(object);
      this.centerCamera(object);
      this.renderer.render(this.scene, this.camera);
    });
  }

  public animate() {
    this.animationFrameId = requestAnimationFrame(() => this.animate());

    this.controls && this.controls.update();
    this.directionLight &&
      this.directionLight.position.copy(this.camera.position);

    this.renderer && this.renderer.render(this.scene, this.camera);
  }

  public centerCamera(object: THREE.Object3D) {
    // const box3 = new THREE.Box3()
    // box3.setFromObject(object)
    // const center = box3.getCenter(new THREE.Vector3())
    // const distance = box3.getSize(new THREE.Vector3()).length()
    // const cameraOffset = distance / Math.tan(THREE.MathUtils.degToRad(this.camera.fov * 0.6))
    // const cameraPosition = center.clone().add(new THREE.Vector3(0, 0, cameraOffset))
    // this.camera.position.copy(cameraPosition)
    // this.controls.target.copy(center)
    // // 更新OrbitControls
    // this.controls.update()

    // 根据模型的尺寸和相机的视角调整相机位置和透视投影
    const boundingBox = new THREE.Box3();
    boundingBox.setFromObject(object);
    const center = boundingBox.getCenter(new THREE.Vector3());
    this.controls.target.copy(center);

    const modelSize = boundingBox.getSize(new THREE.Vector3());

    if (this.camera instanceof THREE.OrthographicCamera) {
      // 计算适当的zoom值，使模型最大化显示
      const maxModelSize = Math.max(modelSize.x, modelSize.y, modelSize.z);
      // const aspect = window.innerWidth / window.innerHeight
      const distance =
        maxModelSize / (2 * Math.tan((this.camera.top * Math.PI) / 360));
      // this.initZoom = 2 / maxModelSize // 模型越大，zoom越小；其中 2 是经验值
      this.camera.zoom = 1 / maxModelSize; // 模型越大，zoom越小；其中 2 是经验值
      this.camera.position.set(0, 0, distance);
      this.camera.updateProjectionMatrix();
    }
  }

  public dispose() {
    cadAppLog('dispose', this.animationFrameId);
    if (!this.renderer) return;
    try {
      cancelAnimationFrame(this.animationFrameId); // animationFrameId = requestAnimationFrame(this.render);
      this.renderer.dispose();
      this.renderer.forceContextLoss();
      this.renderer['content'] = null;
      const gl = this.renderer.domElement.getContext('webgl');
      if (gl && gl.getExtension('WEBGL_lose_context')) {
        gl.getExtension('WEBGL_lose_context').loseContext();
      }
      this.renderer = null;
      this.camera = null;
      this.scene.traverse((child) => {
        if (child['material']) {
          child['material'].dispose();
        }
        if (child['geometry']) {
          child['geometry'].dispose();
        }
        child = null;
      });
      this.scene = null;
    } catch (e) {
      console.error('Failed to destroy threejs', e);
    }
  }
}
